IFN StrCmp(macro.name,'exec/types') THEN FPrintF(f,'MODULE\t''\s''\n',macro.name)
CASE MT_ifdef
FPrintF(f,'#ifdef \s\n',macro.name)
CASE MT_ifndef
FPrintF(f,'#ifndef \s\n',macro.name)
CASE MT_endif
FPrintF(f,'#endif\n',NIL)
CASE MT_if
FPrintF(f,'#if \s\n',macro.name)
CASE MT_undef
FPrintF(f,'#undefine \s\n',macro.name)
CASE MT_else
FPrintF(f,'#else\n',NIL)
ENDSELECT
ENDPROC
PROC WriteCONST(f,const:PTR TO oconst)(PTR TO oconst)
FPrintF(f,'CONST\t\s=\d',const.name,const.value)
IF const.next
IF const.next.what=DA_OConst
IF const:=.next
WHILE const.what=DA_OConst
FPrintF(f,',\n\t\t\s=\d',const.name,const.value)
EXITIF const.next=NIL
const:=.next
ENDWHILE
ENDIF
FPrintF(f,'\n',NIL)
ENDIF
ELSE FPrintF(f,'\n',NIL)
ENDPROC const
PROC ItemLen(item:PTR TO item)(L)
DEF l,ptr
l:=IF item.name THEN StrLen(item.name) ELSE 0
IF item.size THEN l+=StrLen(item.size)+2
IF item.obj THEN l+=StrLen(item.obj)
SELECT item.type&$1f // add ':type'
CASE DT_PTR; l+=4
CASE DT_LONG,DT_WORD,DT_BYTE,DT_BOOL,DT_VOID; l+=5
CASE DT_ULONG,DT_UWORD,DT_UBYTE,DT_FLOAT; l+=6
CASE DT_DOUBLE; l+=7
DEFAULT; l++
ENDSELECT
ptr:=item.type>>5
l+=ptr*7 // length of 'PTR TO '
ENDPROC l
PROC TypeStr(type)(PTR TO CHAR)
DEF str:PTR TO CHAR
SELECT type
CASE 1; str:='LONG'
CASE 2; str:='ULONG'
CASE 3; str:='WORD'
CASE 4; str:='UWORD'
CASE 5; str:='BYTE'
CASE 6; str:='UBYTE'
CASE 7; str:='FLOAT'
CASE 8; str:='DOUBLE'
CASE 9; str:='BOOL'
CASE 10; str:=NIL
CASE 11; str:='PTR'
CASE 12; str:='DLONG'
CASE 13; str:='UDLONG'
CASE 14; str:='STRING'
CASE 33; str:='PTR TO LONG'
CASE 34; str:='PTR TO ULONG'
CASE 35; str:='PTR TO WORD'
CASE 36; str:='PTR TO UWORD'
CASE 37; str:='PTR TO BYTE'
CASE 38; str:='PTR TO UBYTE'
CASE 39; str:='PTR TO FLOAT'
CASE 40; str:='PTR TO DOUBLE'
CASE 41; str:='PTR TO BOOL'
CASE 42; str:='PTR TO '
CASE 43; str:='PTR TO PTR'
CASE 44; str:='PTR TO DLONG'
CASE 45; str:='PTR TO UDLONG'
CASE 46; str:='PTR TO CHAR'
CASE 65; str:='PTR TO PTR TO LONG'
CASE 66; str:='PTR TO PTR TO ULONG'
CASE 67; str:='PTR TO PTR TO WORD'
CASE 68; str:='PTR TO PTR TO UWORD'
CASE 69; str:='PTR TO PTR TO BYTE'
CASE 70; str:='PTR TO PTR TO UBYTE'
CASE 71; str:='PTR TO PTR TO FLOAT'
CASE 72; str:='PTR TO PTR TO DOUBLE'
CASE 73; str:='PTR TO PTR TO BOOL'
CASE 74; str:='PTR TO PTR TO '
CASE 75; str:='PTR TO PTR TO PTR'
CASE 76; str:='PTR TO PTR TO DLONG'
CASE 77; str:='PTR TO PTR TO UDLONG'
CASE 78; str:='PTR TO PTR TO CHAR'
CASE 129;str:='LIST OF LONG'
CASE 130;str:='LIST OF ULONG'
CASE 131;str:='LIST OF WORD'
CASE 132;str:='LIST OF UWORD'
CASE 133;str:='LIST OF BYTE'
CASE 134;str:='LIST OF UBYTE'
CASE 135;str:='LIST OF FLOAT'
CASE 136;str:='LIST OF DOUBLE'
CASE 137;str:='LIST OF BOOL'
CASE 138;str:='LIST OF '
CASE 139;str:='LIST OF PTR'
CASE 140;str:='LIST OF DLONG'
CASE 141;str:='LIST OF UDLONG'
CASE 142;str:='LIST OF CHAR'
DEFAULT; str:='VOID'
ENDSELECT
ENDPROC str
PROC GetNum(s:PTR TO CHAR,n=0,l)(LONG,LONG)
DEF num=0,sign=1
WHILE s[n]="\t" OR s[n]="\n" OR s[n]=" " DO n++
IF s[n]="-"
sign:=-1
n++
ENDIF
IF s[n]="0" AND s[n+1]="x" // HEXADECIMAL number
n+++
WHILE s[n]>="0" AND s[n]<="9"
num<<=4
num|=s[n]-"0"
ELSEWHILE s[n]>="a" AND s[n]<="f"
num<<=4
num|=s[n]-"a"+10
ELSEWHILE s[n]>="A" AND s[n]<="F"
num<<=4
num|=s[n]-"A"+10
ALWAYS
n++
IF n>l THEN Raise("EOF",n)
ENDWHILE
ELSE // DECIMAL number
WHILE s[n]>="0" AND s[n]<="9"
num*=10
num+=s[n]-"0"
n++
IF n>l THEN Raise("EOF",n)
ENDWHILE
ENDIF
ENDPROC n,num*sign
PROC GetName(name:PTR TO CHAR,src:PTR TO CHAR,pos,length,istype=FALSE)(L,PTR)
DEF i=0,c=1
IF name
IF IsAlpha2(src[pos])
WHILE c
WHILE IsAlpha2Num(src[pos])
name[i]:=src[pos]
pos++
i++
CtrlC()
IF pos>length THEN Raise("EOF",pos)
ENDWHILE
name[i]:="\0"
c--
IF istype
IF StrCmp(name,'unsigned')
name[i++]:=" "
pos:=Skip(src,pos,length)
c:=1
ENDIF
ENDIF
ENDWHILE
ENDIF
ELSE
IF IsAlpha2(src[pos])
WHILE IsAlpha2Num(src[pos])
pos++
CtrlC()
IF pos>length THEN Raise("EOF",pos)
ENDWHILE
name:=TRUE
ENDIF
ENDIF
ENDPROC pos,name
PROC GetString(str:PTR TO CHAR,src:PTR TO CHAR,pos,length)(L,PTR)
DEF i=0
IF (src[pos]=34)||(src[pos]="<")
pos++
WHILE (src[pos]<>34)&&(src[pos]<>">")
str[i]:=src[pos]
pos++
i++
CtrlC()
IF pos>length THEN Raise("EOF",pos)
ENDWHILE
str[i]:="\0"
pos++ // skip ",>
ENDIF
ENDPROC pos,str
PROC Find(char,src:PTR TO CHAR,pos,length)(L)
WHILE src[pos]<>char
pos++
CtrlC()
IF pos>length THEN Raise("EOF",pos)
ENDWHILE
ENDPROC pos
PROC FindTDEF(item:PTR TO typedef,name:PTR TO CHAR)(BOOL)
WHILE item
IF item.what=DA_TDEF
IF StrCmp(item.name,name) THEN RETURN TRUE
ENDIF
CtrlC()
item:=.next
ENDWHILE
ENDPROC FALSE
PROC IsAlpha2(char)(L) IS IF ((char>="A")&&(char<="Z"))||((char>="a")&&(char<="z"))||(char="_")||(char="#") THEN TRUE ELSE FALSE
PROC IsAlpha2Num(char)(L) IS IF ((char>="A")&&(char<="Z"))||((char>="a")&&(char<="z"))||(char="_")||((char>="0")&&(char<="9"))||(char="#") THEN TRUE ELSE FALSE
PROC IsFirstNum(char)(L) IS IF ((char>="0")&&(char<="9"))||(char=".")||(char="$")||(char="%")||(char="-") THEN TRUE ELSE FALSE
// skip whitespaces and comments
PROC Skip(src:PTR TO CHAR,pos,length)(L)
DEF done=FALSE,char
REPEAT
char:=src[pos]
IF char=" "
pos++
ELSEIF char="\t"
pos++
ELSEIF char=";"
pos++
ELSEIF char="\n"
pos++
ELSEIF char="/"
IF src[pos+1]="*"
pos++
REPEAT
pos++
IF pos>length THEN RETURN pos
UNTIL (src[pos-1]="*")&&(src[pos]="/")
pos++
ELSEIF src[pos+1]="/"
pos++
REPEAT
pos++
IF pos>length THEN RETURN pos
UNTIL (src[pos]="\n")||((src[pos-1]="/")&&(src[pos]="/"))
pos++
ELSE
done:=TRUE
ENDIF
ELSE
done:=TRUE
ENDIF
IF pos>length THEN Raise("EOF",pos)
UNTIL done=TRUE
ENDPROC pos
// skip whitespaces only
PROC Crop(src:PTR TO CHAR,pos,length)(L)
DEF done=FALSE,char
REPEAT
char:=src[pos]
IF char=" "
pos++
ELSEIF char="\t"
pos++
ELSEIF char=";"
pos++
ELSEIF char="\n"
pos++
ELSE
done:=TRUE
ENDIF
IF pos>length THEN Raise("EOF",pos)
UNTIL done=TRUE
ENDPROC pos
PROC MaCrop(src:PTR TO CHAR,pos,length)(L)
DEF cpos=-1,qpos=-1,apos=-1
WHILE src[pos]<>"\n"
IF src[pos]="/" AND src[pos+1]="/" THEN cpos:=0
IF src[pos]="/" AND src[pos+1]="*" THEN cpos:=0
IF src[pos]="*" AND src[pos+1]="/" THEN cpos:=-1
IF src[pos]="\q" THEN qpos:=~qpos
IF src[pos]="\a" THEN apos:=~apos
IF src[pos]="\\" THEN IF cpos=-1 AND qpos=-1 AND apos=-1 THEN RETURN pos
pos++
IF pos>length THEN Raise("EOF",pos)
ENDWHILE
ENDPROC pos
PROC Optimize(first:PTR TO data)(PTR)
DEF prev=NIL:PTR TO data,data=first:PTR TO data,cnst:PTR TO oconst
DEF macro:PTR TO macro,mline:PTR TO mline,bool:BOOL,flt:BOOL,value
// change all number-only macros to constants
WHILE data
IF data.what=DA_Macro
macro:=data
IF macro.type=MT_define && macro.args=NIL
IF mline:=macro.mline
IF mline.next=NIL
IF bool,flt:=CheckNumber(mline.data)
IFN flt
cnst:=AllocPooled(pool,SIZEOF_oconst)
cnst.what:=DA_OConst
cnst.next:=data.next
cnst.name:=macro.name
value:=Val(mline.data)
cnst.value:=value
cnst.comment:=mline.comment
IF prev THEN prev.next:=cnst ELSE first:=cnst
data:=cnst
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
prev:=data
data:=.next
CtrlC()
ENDWHILE
ENDPROC first
PROC CheckNumber(str:PTR TO CHAR)(BOOL,BOOL)
DEF number=TRUE:BOOL,n=0,float=FALSE:BOOL
n:=Crop(str,0,StrLen(str))
IF IsFirstNum(str[n])
n++
WHILE str[n]
IF IsHex(str[n])
ELSEIF str[n]="."; float:=TRUE
ELSE number:=FALSE
n++
ENDWHILE
ELSE number:=FALSE
ENDPROC number,float
PROC ComputeMacro(first:PTR TO data,macro:PTR TO macro)
DEF line:PTR TO mline,name[64]:STRING,pos,len,npos